using System;
using GodProject.peoples;

namespace GodProject.generators
{
  class SimplePeoplesRandomizer : IPeoplesRandomizer
  {
    #region settings
    /// <summary>
    /// Student's age lower bound
    /// </summary>
    private const int StudentAgeLowerBound = 17;
    /// <summary>
    /// Student's age upper bound
    /// </summary>
    private const int StudentAgeUpperBound = 30;

    /// <summary>
    /// Parent's child count min value
    /// </summary>
    private const int ChildCountMin = 1;
    /// <summary>
    /// Parent's child count max value
    /// </summary>
    private const int ChildCountMax = 5;

    /// <summary>
    /// Parent's age lower bound
    /// </summary>
    private const int ParentAgeLowerBound = 35;
    /// <summary>
    /// Parent's age upper bound
    /// </summary>
    private const int ParentAgeUpperBound = 70;

    /// <summary>
    /// Botan's average mark min
    /// </summary>
    private const double BotanAverageMarkMin = 3.1;
    /// <summary>
    /// Botan's average mark max
    /// </summary>
    private const double BotanAverageMarkMax = 5;

    /// <summary>
    /// Value for randomization type's generator
    /// </summary>
    private const int TypGenratorRandomization = 1000;

    #endregion settings

    /// <summary>
    /// Random, used for generation random values
    /// </summary>
    private readonly Random _random = new Random();

    #region random human's property generation

    /// <summary>
    /// Generates random student age
    /// </summary>
    /// <returns>random student age</returns>
    public int CalculateRandomStudentAge()
    {
      return _random.Next(StudentAgeLowerBound, StudentAgeUpperBound);
    }

    /// <summary>
    /// Generates random parent's age
    /// </summary>
    /// <returns>random parent's age</returns>
    public int CalculateRandomParentAge()
    {
      return _random.Next(ParentAgeLowerBound, ParentAgeUpperBound);
    }

    /// <summary>
    /// Generates random child count
    /// </summary>
    /// <returns>random child count</returns>
    public int CalculateRandomChildCount()
    {
      return _random.Next(ChildCountMin, ChildCountMax);
    }

    /// <summary>
    /// Generates random avg marks
    /// </summary>
    /// <returns>random avg marks</returns>
    public double CalculateRandomAvgMarks()
    {
      return _random.NextDouble() * (BotanAverageMarkMax - BotanAverageMarkMin) + BotanAverageMarkMin;
    }

    /// <summary>
    /// Generates random cool parent's money
    /// </summary>
    /// <returns>random cool parent's money</returns>
    public double CalculateRandomMoney()
    {
      double rnd = _random.NextDouble() * (BotanAverageMarkMax - BotanAverageMarkMin) + BotanAverageMarkMin;
      return Math.Pow(10, rnd);
    }

    /// <summary>
    /// Generates random sex
    /// </summary>
    /// <returns>random sex</returns>
    public Sex GenerateRandomSex()
    {
      return _random.Next() % 2 == 0 ? Sex.Male : Sex.Female;
    }

    /// <summary>
    /// Generate random type of human
    /// </summary>
    /// <returns></returns>
    public HumanType GenerateRandomType()
    {
      int type = _random.Next(0, TypGenratorRandomization) % 4;
      switch (type)
      {
        case 0:
        return HumanType.Botan;
        case 1:
        return HumanType.CoolParent;
        case 2:
        return HumanType.Parent;
        case 3:
        default:
        return HumanType.Student;
      }
    }

    /// <summary>
    /// Generates random type from types, for witch Female sex is available
    /// </summary>
    /// <returns>Student or Botan</returns>
    private HumanType GenerateRandomFromFemaleTypes()
    {
      int type = _random.Next(0, TypGenratorRandomization) % 2;
      switch (type)
      {
        case 0:
        return HumanType.Botan;
        default:
        return HumanType.Student;
      }
    }

    /// <summary>
    /// Generates random human type by sex 
    /// (that's because parents can be male only)
    /// </summary>
    /// <param name="sex">sex of human to be generated</param>
    /// <returns>random human type</returns>
    public HumanType GenerateRandomType(Sex sex)
    {
      switch (sex)
      {
        case Sex.Female:
        return GenerateRandomType();
        default:
        return GenerateRandomFromFemaleTypes();
      }
    }
  }
    #endregion random human's property generation


}